﻿using System;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Security.Cryptography;
using System.Text;

using com.vs.General;

namespace com.vs.General.BL
{
    /// <summary>
    /// Summary description for LicenseKeyProcessing.
    /// </summary>
    public class LicenseKeyProcessing
    {
        public LicenseKeyProcessing()
        {
        }

        public string ProcessLicenseKey(string stMachineName, int iNumUsers,
                                        DateTime dtExpirationDate, string stExpirationAction,
                                        string stModules, string stFile, string stDir, string stBiosSerialNum,
                                        LicenseKeyConstants.LicenseKeyType licenseType)
        {
            string stLicenseKey = null;
            string stError = null;
            bool bResult = false;

            try
            {
                bResult = this.isDataValid(stMachineName, iNumUsers, DateTime.Now, dtExpirationDate,
                    stExpirationAction, stModules, stFile, stDir, ref stError, stBiosSerialNum);

                //If any of the entered data is invalid return the error and exit function.
                if (!bResult)
                    return stError;

                //If all entered values are valid, Construct the Licensekey
                stLicenseKey = this.constructLicenseKey(stMachineName, iNumUsers, 
                    DateTime.Now, dtExpirationDate, stExpirationAction, stModules, stFile,
                    stDir, stBiosSerialNum, licenseType);

                return this.ProcessLicenseKey(stLicenseKey, stFile, stDir);

            }
            catch (Exception exp)
            {
                throw exp;
            }
        }//end processLicenseKey

        private bool isDataValid(string stMachineName, int iNumUsers,
                                 DateTime creationDate, DateTime dtExpirationDate, string stExpirationAction,
                                 string stModules, string stFile, string stDir, ref string stError,
                                 string stBiosSerialNum)
        {
            int timeSpan;

            if (StringManager.IsEmpty(stMachineName))
            {
                stError = MessageManager.MSG_LIC_002; //机器名不能为空
                return false;
            }

            if (iNumUsers <= 0)
            {
                return false;
            }

            timeSpan = dtExpirationDate.CompareTo(creationDate);
            if (timeSpan <= 0)
            {
                stError = MessageManager.MSG_LIC_003; //到期日必须晚于当前日期
                return false;
            }

            if (!Directory.Exists(stDir))
            {
                stError = MessageManager.MSG_LIC_004; //授权文件存放目录不存在
                return false;
            }

            stError = null;
            return true;
        }

        private string constructLicenseKey(string stMachineName, int iNumUsers,
                                           DateTime creationDate, DateTime dtExpirationDate, string stExpirationAction,
                                           string stModules, string stFile, string stDir,
                                           string stBiosSerialNum, LicenseKeyConstants.LicenseKeyType licenseType)
        {

            string stLicenseKey = null;

            stLicenseKey = LicenseKeyConstants.stLICENSEKEYBIOSSERIALNUM + LicenseKeyConstants.stCOLON + stBiosSerialNum;
            stLicenseKey += LicenseKeyConstants.stDODELIM;

            stLicenseKey += LicenseKeyConstants.stLICENSEKEYMACHINENAME + LicenseKeyConstants.stCOLON + stMachineName;
            stLicenseKey += LicenseKeyConstants.stDODELIM;

            stLicenseKey += LicenseKeyConstants.stLICENSEKEYNUMBEROFUSERS + LicenseKeyConstants.stCOLON + iNumUsers.ToString();
            stLicenseKey += LicenseKeyConstants.stDODELIM;

            stLicenseKey += LicenseKeyConstants.stLICENSEKEYEXPIRATIONDATE + LicenseKeyConstants.stCOLON + DateManager.ToStringWithInvariantCulture(dtExpirationDate);
            stLicenseKey += LicenseKeyConstants.stDODELIM;

            stLicenseKey += LicenseKeyConstants.stLICENSEKEYEXPIRATIONACTION + LicenseKeyConstants.stCOLON + stExpirationAction;
            stLicenseKey += LicenseKeyConstants.stDODELIM;

            stLicenseKey += LicenseKeyConstants.stLICENSEKEYMODULES + LicenseKeyConstants.stCOLON + stModules;
            stLicenseKey += LicenseKeyConstants.stDODELIM;

            stLicenseKey += LicenseKeyConstants.stLICENSEKEYCREATIONDATE + LicenseKeyConstants.stCOLON + DateManager.ToStringWithInvariantCulture(creationDate);
            stLicenseKey += LicenseKeyConstants.stDODELIM;

            stLicenseKey += LicenseKeyConstants.stLICENSEKEYLICENSETYPE + LicenseKeyConstants.stCOLON + licenseType;

            return stLicenseKey;
        }

        //This method retrieves the security key and the Initialization Vector from the Config file.		
        //These values are passed by reference
        private void constructSecurityKeyAndIV(ref string stSecKey, ref string stIV)
        {
            stSecKey = "ILOVEMAYKID";
            stIV = "MAYKIDLOVESME";
        }


        //Creates the file that stores the encrypted license key. 
        private void createLicenseFile(string stLicenseKey, string stFileName, string stDirName)
        {
            FileManager.Write(stFileName, LicenseKeyConstants.stLICENSE_FILE_EXT, stLicenseKey);
        }//End of createLicenseFile


        #region ProcessLicenseKey
        /// <summary>
        /// This method encrypts the license and writes to the license file provided
        /// </summary>
        /// <param name="license">License</param>
        /// <param name="file">license file</param>
        /// <param name="dir">license file directory</param>
        /// <returns></returns>
        public string ProcessLicenseKey(string license, string file, string dir)
        {
            string stSecurityKey = null;
            string stIV = null;
            string stError = null;
            string stEncryptedFilePath = null;
            byte[] byteSecurityKey;
            byte[] byteFinalSecurityKey;
            byte[] byteIV;
            byte[] byteFinalIV;

            ASCIIEncoding textConverter;
            MD5CryptoServiceProvider cryptoServiceProvider;

            //Retrieve the Securitykey and Initialization Vector
            this.constructSecurityKeyAndIV(ref stSecurityKey, ref stIV);

            //Create ASCIIEncoding object and MD5CryptoServiceProvider object
            textConverter = new ASCIIEncoding();
            cryptoServiceProvider = new MD5CryptoServiceProvider();

            //Convert the SecurityKey to bytes
            byteSecurityKey = textConverter.GetBytes(stSecurityKey);
            byteFinalSecurityKey = cryptoServiceProvider.ComputeHash(byteSecurityKey);

            //Convert the IV to bytes
            byteIV = textConverter.GetBytes(stIV);
            byteFinalIV = cryptoServiceProvider.ComputeHash(byteIV);

            //Construct the filepath
            stEncryptedFilePath = dir + "\\" + file;
            if (!stEncryptedFilePath.Trim().EndsWith(LicenseKeyConstants.stLICENSE_FILE_EXT))
                stEncryptedFilePath = stEncryptedFilePath + "." + LicenseKeyConstants.stLICENSE_FILE_EXT;

            //Encrypt the license key and write the output to the 
            EncryptionManager.EncryptDataToFile(license,
                stEncryptedFilePath,
                byteFinalSecurityKey,
                byteFinalIV);

            return stError;
        }
        #endregion
    }//End of class
}//End of namespace